<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Circuit Construction &mdash; pytket-manual  documentation</title>
      <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
      <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
      <link rel="stylesheet" href="_static/jupyter-sphinx.css" type="text/css" />
      <link rel="stylesheet" href="_static/thebelab.css" type="text/css" />
  <!--[if lt IE 9]>
    <script src="_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
        <script src="_static/jquery.js"></script>
        <script src="_static/underscore.js"></script>
        <script src="_static/doctools.js"></script>
        <script src="_static/thebelab-helper.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
        <script src="https://unpkg.com/@jupyter-widgets/html-manager@^0.20.0/dist/embed-amd.js"></script>
        <script async="async" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
    <script src="_static/js/theme.js"></script>
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Running on Backends" href="manual_backend.html" />
    <link rel="prev" title="What is tket?" href="manual_intro.html" /> 
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
            <a href="index.html" class="icon icon-home"> pytket-manual
          </a>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
              <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="manual_intro.html">What is tket?</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Circuit Construction</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#basic-gates">Basic Gates</a></li>
<li class="toctree-l2"><a class="reference internal" href="#measurements">Measurements</a></li>
<li class="toctree-l2"><a class="reference internal" href="#barriers">Barriers</a></li>
<li class="toctree-l2"><a class="reference internal" href="#registers-and-ids">Registers and IDs</a></li>
<li class="toctree-l2"><a class="reference internal" href="#composing-circuits">Composing Circuits</a></li>
<li class="toctree-l2"><a class="reference internal" href="#boxes">Boxes</a></li>
<li class="toctree-l2"><a class="reference internal" href="#analysing-circuits">Analysing Circuits</a></li>
<li class="toctree-l2"><a class="reference internal" href="#importing-exporting-circuits">Importing/Exporting Circuits</a></li>
<li class="toctree-l2"><a class="reference internal" href="#symbolic-circuits">Symbolic Circuits</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#symbolic-unitaries-and-states">Symbolic unitaries and states</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#advanced-topics">Advanced Topics</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#custom-parameterised-gates">Custom parameterised Gates</a></li>
<li class="toctree-l3"><a class="reference internal" href="#conditional-gates">Conditional Gates</a></li>
<li class="toctree-l3"><a class="reference internal" href="#circuit-level-operations">Circuit-Level Operations</a></li>
<li class="toctree-l3"><a class="reference internal" href="#implicit-qubit-permutations">Implicit Qubit Permutations</a></li>
<li class="toctree-l3"><a class="reference internal" href="#modifying-operations-within-circuits">Modifying Operations Within Circuits</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="manual_backend.html">Running on Backends</a></li>
<li class="toctree-l1"><a class="reference internal" href="manual_compiler.html">Compilation</a></li>
<li class="toctree-l1"><a class="reference internal" href="manual_noise.html">Noise and the Quantum Circuit Model</a></li>
<li class="toctree-l1"><a class="reference internal" href="manual_assertion.html">Assertion</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">More documentation:</span></p>
<ul>
<li class="toctree-l1"><a class="reference external" href="https://cqcl.github.io/tket/pytket/api/index.html">pytket</a></li>
</ul>

        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="index.html">pytket-manual</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="index.html" class="icon icon-home"></a> &raquo;</li>
      <li>Circuit Construction</li>
      <li class="wy-breadcrumbs-aside">
            <a href="_sources/manual_circuit.rst.txt" rel="nofollow"> View page source</a>
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <div class="section" id="circuit-construction">
<h1>Circuit Construction<a class="headerlink" href="#circuit-construction" title="Permalink to this headline"></a></h1>
<p>The <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> class forms the unit of computation that we can send off to a quantum co-processor. Each instruction is to be performed in order, potentially parallelising when they use disjoint sets of (qu)bits. To capture this freedom of parallelisation, we treat the circuit as a Directed Acyclic Graph with a vertex for each instruction and directed edges following the paths of resources (e.g. qubits and bits) between them. This DAG representation describes the abstract circuit ignoring these trivial commutations/parallel instructions.</p>
<p>In general, we consider <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> instances to represent open circuits; that is, they can be used within arbitrary contexts, so any input state can be supplied and there is no assumption on how the output state should be used. In practice, when we send a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> off to be executed, it will be run with all qubits in the initial state <span class="math notranslate nohighlight">\(|0\rangle^{\otimes n}\)</span> and all bits set to <span class="math notranslate nohighlight">\(0\)</span>, then the classical outputs returned and the quantum state discarded.</p>
<p>Each circuit can be represented as a POVM on the combined quantum/classical state space by composing the representations assigned to each basic instruction. However, many use cases will live predominantly in the pure quantum space where the operations are simply unitaries acting on the quantum state. One practical distinction between these cases is the relevance of global phase: something that cannot be identified at the POVM level but has importance for pure states as it affects how we interpret the system and has an observable difference when the system is then coherently controlled. For example, an Rz gate and a U1 gate give equivalent effects on the quantum state but have a different global phase, meaning their unitaries <em>look</em> different, and a controlled-Rz is different from a controlled-U1. A <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> will track global phase to make working with pure quantum processes easier, though this becomes meaningless once measurements and other classical interaction are applied and has no impact on the instructions sent to a quantum device when we eventually run it.</p>
<p>Given the small scale and lack of dynamic quantum memories for both devices and simulations, we assume each qubit and bit is statically registered and hence each <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> has the same number of inputs as outputs. The set of data units (qubits and bits) used by the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> is hence going to be constant, so we can define it up-front when we construct one. We can also optionally give it a name for easy identification.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">trivial_circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>        <span class="c1"># no qubits or bits</span>
<span class="n">quantum_circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>       <span class="c1"># 4 qubits and no bits</span>
<span class="n">mixed_circ</span>   <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>    <span class="c1"># 4 qubits and 2 bits</span>
<span class="n">named_circ</span>   <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">&quot;my_circ&quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
</div>
</div>
<div class="section" id="basic-gates">
<h2>Basic Gates<a class="headerlink" href="#basic-gates" title="Permalink to this headline"></a></h2>
<p>The bulk of the interaction with a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> object will be in building up the sequence of instructions to be run. The simplest way to do this is by adding each instruction in execution order to the end of the circuit.</p>
<p>Basic quantum gates represent some unitary operation applied to some qubits. Adding them to a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> just requires specifying which qubits you want to apply them to. For controlled-gates, the convention is to give the control qubit(s) first, followed by the target qubit(s).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>   <span class="c1"># qubits are numbered 0-3</span>
<span class="n">circ</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>           <span class="c1"># first apply an X gate to qubit 0</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>       <span class="c1"># and apply a CX gate with control qubit 1</span>
                    <span class="c1">#   and target qubit 3</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Z</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>           <span class="c1"># then apply a Z gate to qubit 3</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[X q[0]; CX q[1], q[3]; Z q[3]; ]
</pre></div>
</div>
</div>
</div>
<p>For parameterised gates, such as rotations, the parameter is always given first. Because of the prevalence of rotations with angles given by fractions of <span class="math notranslate nohighlight">\(\pi\)</span> in practical quantum computing, the unit for all angular parameters is the half-turn (1 half-turn is equal to <span class="math notranslate nohighlight">\(\pi\)</span> radians).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>     <span class="c1"># Rx of angle pi/2 radians on qubit 0</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CRz</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1"># Controlled-Rz of angle 0.3pi radians with</span>
                    <span class="c1">#   control qubit 1 and target qubit 0</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(0.5) q[0]; CRz(0.3) q[1], q[0]; ]
</pre></div>
</div>
</div>
</div>
<p>A large selection of common gates are available in this way, as listed in the API reference for the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> class. However, for less commonly used gates, a wider variety is available using the <code class="xref py py-class docutils literal notranslate"><span class="pre">OpType</span></code> enum, which can be added using the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit.add_gate</span></code> method.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">OpType</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">CnX</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
    <span class="c1"># add controlled-X with control qubits 0, 1, 4 and target qubit 3</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">XXPhase</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">])</span>
    <span class="c1"># add e^{-i (0.7 pi / 2) XX} on qubits 0 and 2</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">PhasedX</span><span class="p">,</span> <span class="p">[</span><span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">])</span>
    <span class="c1"># adds Rz(-0.5 pi); Rx(-0.1 pi); Rz(0.5 pi) on qubit 3</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[CnX q[0], q[1], q[4], q[3]; Mølmer-Sørensen(0.7) q[0], q[2]; PhasedX(3.9, 0.5) q[3]; ]
</pre></div>
</div>
</div>
</div>
<p>The API reference for the <code class="xref py py-class docutils literal notranslate"><span class="pre">OpType</span></code> class details all available operations that can exist in a circuit.</p>
<p>In the above example, we asked for a <code class="docutils literal notranslate"><span class="pre">PhasedX</span></code> with angles <code class="docutils literal notranslate"><span class="pre">[-0.1,</span> <span class="pre">0.5]</span></code>, but received <code class="docutils literal notranslate"><span class="pre">PhasedX(3.9,</span> <span class="pre">0.5)</span></code>. <code class="docutils literal notranslate"><span class="pre">pytket</span></code> will freely map angles into the range <span class="math notranslate nohighlight">\(\left[0, r\right)\)</span> for some range parameter <span class="math notranslate nohighlight">\(r\)</span> that depends on the <code class="xref py py-class docutils literal notranslate"><span class="pre">OpType</span></code>, preserving the unitary matrix (including global phase).</p>
</div>
<div class="section" id="measurements">
<h2>Measurements<a class="headerlink" href="#measurements" title="Permalink to this headline"></a></h2>
<p>Measurements go a step further by interacting with both the quantum and classical data. The convention used in <code class="docutils literal notranslate"><span class="pre">pytket</span></code> is that all measurements are non-destructive, single-qubit measurements in the <span class="math notranslate nohighlight">\(Z\)</span> basis; other forms of measurements can be constructed by combining these with other operations.</p>
<p>Adding a measurement works just like adding any other gate, where the first argument is the qubit to be measured and the second specifies the classical bit to store the result in.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>  <span class="c1"># Z-basis measurement on qubit 0, saving result in bit 0</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>  <span class="c1"># Measurement of IXXX, saving result in bit 1</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Measure q[0] --&gt; c[0]; CX q[1], q[2]; CX q[1], q[3]; H q[1]; Measure q[1] --&gt; c[1]; ]
</pre></div>
</div>
</div>
</div>
<p>Because the classical bits are treated as statically assigned locations, writing to the same bit multiple times will overwrite the previous value.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>  <span class="c1"># measure the first measurement</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>  <span class="c1"># overwrites the first result with a new measurement</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Measure q[0] --&gt; c[0]; CX q[0], q[1]; Measure q[1] --&gt; c[0]; ]
</pre></div>
</div>
</div>
</div>
<p>Depending on where we plan on running our circuits, the backend or simulator might have different requirements on the structure of measurements in the circuits. For example, statevector simulators will only work deterministically for pure-quantum circuits, so will fail if any measures are present at all. More crucially, near-term quantum hardware almost always requires all measurements to occur in a single parallel layer at the end of the circuit (i.e. we cannot measure a qubit in the middle of the circuit).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ0</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>    <span class="c1"># all measurements at end</span>
<span class="n">circ0</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">circ0</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ0</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">circ1</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>    <span class="c1"># this is DAG-equivalent to circ1, so is still ok</span>
<span class="n">circ1</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ1</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">circ1</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">circ2</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
    <span class="c1"># reuses qubit 0 after measuring, so this may be rejected by a device</span>
<span class="n">circ2</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ2</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ2</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">circ3</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="c1"># overwriting the classical value means we have to measure qubit 0</span>
    <span class="c1"># before qubit 1; they won&#39;t occur simultaneously so this may be rejected</span>
<span class="n">circ3</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ3</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Measure q[0] --&gt; c[0]; Measure q[1] --&gt; c[0]; ]
</pre></div>
</div>
</div>
</div>
<p>The simplest way to guarantee this is to finish the circuit by measuring all qubits. There is a short-hand function <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.measure_all()</span></code> to make this easier.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="c1"># measure qubit 0 in Z basis and 1 in X basis</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">measure_all</span><span class="p">()</span>

<span class="c1"># measure_all() adds bits if they are not already defined, so equivalently</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">measure_all</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Measure q[0] --&gt; c[0]; H q[1]; Measure q[1] --&gt; c[1]; ]
</pre></div>
</div>
</div>
</div>
<p>On devices where mid-circuit measurements are available, they may be highly noisy and not apply just a basic projector on the quantum state. We can view these as “effectively destructive” measurements, where the qubit still exists but is in a noisy state. In this case, it is recommended to actively reset a qubit after measurement if it is intended to be reused.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">OpType</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="c1"># Actively reset state to |0&gt;</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">Reset</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="c1"># Conditionally flip state to |1&gt; to reflect measurement result</span>
<span class="n">circ</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">condition_bits</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">condition_value</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="c1"># Use the qubit as if the measurement was non-destructive</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Measure q[0] --&gt; c[0]; Reset q[0]; IF ([c[0]] == 1) THEN X q[0]; CX q[0], q[1]; ]
</pre></div>
</div>
</div>
</div>
</div>
<div class="section" id="barriers">
<h2>Barriers<a class="headerlink" href="#barriers" title="Permalink to this headline"></a></h2>
<p>The concept of barriers comes from low-level classical programming. They exist as instructions but perform no active operation. Instead, their function is twofold:</p>
<ul class="simple">
<li><p>At compile-time, prevent the compiler from reordering operations around the barrier.</p></li>
<li><p>At runtime, ensure that all operations before the barrier must have finished before any operations after the barrier start.</p></li>
</ul>
<p>The intention is the same for <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s. Inserting barriers can be used to segment the program to easily spot how it is modified during compilation, and some quantum hardware uses barriers as the primary method of embedding timing information.</p>
<p>Adding a barrier to a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> is done using the <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.add_barrier()</span></code> method. In general, a barrier is placed on some subset of the (qu)bits to impose these ordering restrictions on those (qu)bits specifically (i.e. we don’t care about reorders on the other (qu)bits).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_barrier</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> <span class="c1"># add a barrier on all qubits and bits</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[H q[0]; CX q[1], q[2]; Barrier q[0], q[1], q[2], q[3], c[0], c[1]; Measure q[0] --&gt; c[0]; Measure q[2] --&gt; c[1]; ]
</pre></div>
</div>
</div>
</div>
</div>
<div class="section" id="registers-and-ids">
<h2>Registers and IDs<a class="headerlink" href="#registers-and-ids" title="Permalink to this headline"></a></h2>
<p>Using integer values to refer to each of our qubits and bits works fine for small-scale experiments, but when building up larger and more complicated programs, it is much easier to manage if we are able to name the resources to attach semantic meaning to them and group them into related collections. <code class="docutils literal notranslate"><span class="pre">pytket</span></code> enables this by supporting registers and named IDs.</p>
<p>Each unit resource is associated with a <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code> (typically the subclasses <code class="xref py py-class docutils literal notranslate"><span class="pre">Qubit</span></code> or <code class="xref py py-class docutils literal notranslate"><span class="pre">Bit</span></code>), which gives a name and some (<span class="math notranslate nohighlight">\(n\)</span>-dimensional) index. A (quantum/classical) register is hence some collection of <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code> s with the same name, dimension of index, and type of associated resource. These identifiers are not necessarily tied to a specific <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> and can be reused between many of them.</p>
<p>Named resources can be added to <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s individually, or by declaring a 1-dimensional register. Any of the methods for adding gates can then use these IDs.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span><span class="p">,</span> <span class="n">Bit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="n">qreg</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_q_register</span><span class="p">(</span><span class="s2">&quot;reg&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>    <span class="c1"># add a qubit register</span>

<span class="n">anc</span> <span class="o">=</span> <span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;ancilla&quot;</span><span class="p">)</span>                  <span class="c1"># add a named qubit</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">anc</span><span class="p">)</span>

<span class="n">par</span> <span class="o">=</span> <span class="n">Bit</span><span class="p">(</span><span class="s2">&quot;parity&quot;</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>             <span class="c1"># add a named bit with a 2D index</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_bit</span><span class="p">(</span><span class="n">par</span><span class="p">)</span>

<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">anc</span><span class="p">)</span>                   <span class="c1"># add gates in terms of IDs</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">anc</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="n">anc</span><span class="p">,</span> <span class="n">par</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[CX reg[0], ancilla; CX reg[1], ancilla; Measure ancilla --&gt; parity[0, 0]; ]
</pre></div>
</div>
</div>
</div>
<p>A <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> can be inspected to identify what qubits and bits it contains.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_q_register</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">))</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_c_register</span><span class="p">(</span><span class="s2">&quot;z&quot;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">qubits</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">bits</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[a[0], a[1], a[2], a[3], b]
[z[0], z[1], z[2]]
</pre></div>
</div>
</div>
</div>
<p>To help encourage consistency of identifiers, a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> will reject a new (qu)bit or register if it disagrees with existing IDs with the same name; that is, it refers to a different resource type (qubit vs bit), the index has a different dimension, or some resource already exists with the exact same ID in the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>. Identifiers with the same register name do not have to have contiguous indices (many devices require non-contiguous indices because qubits may be taken offline over the lifetime of the device).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span><span class="p">,</span> <span class="n">Bit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="c1"># set up a circuit with qubit a[0]</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>

<span class="c1"># rejected because &quot;a&quot; is already a qubit register</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_bit</span><span class="p">(</span><span class="n">Bit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output traceback highlight-ipythontb notranslate"><div class="highlight"><pre><span></span><span class="gt">---------------------------------------------------------------------------</span>
<span class="ne">RuntimeError</span><span class="g g-Whitespace">                              </span>Traceback (most recent call last)
<span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">13</span><span class="o">-</span><span class="mi">00</span><span class="n">dbd993ed28</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<span class="g g-Whitespace">      </span><span class="mi">5</span> 
<span class="g g-Whitespace">      </span><span class="mi">6</span> <span class="c1"># rejected because &quot;a&quot; is already a qubit register</span>
<span class="ne">----&gt; </span><span class="mi">7</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_bit</span><span class="p">(</span><span class="n">Bit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>

<span class="ne">RuntimeError</span>: Cannot add bit with ID &quot;a[1]&quot; as register is not compatible
</pre></div>
</div>
</div>
</div>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rejected because &quot;a&quot; is already a 1D register</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]))</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output traceback highlight-ipythontb notranslate"><div class="highlight"><pre><span></span><span class="gt">---------------------------------------------------------------------------</span>
<span class="ne">RuntimeError</span><span class="g g-Whitespace">                              </span>Traceback (most recent call last)
<span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">14</span><span class="o">-</span><span class="mi">71</span><span class="n">f219c8fa9c</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<span class="g g-Whitespace">      </span><span class="mi">1</span> <span class="c1"># rejected because &quot;a&quot; is already a 1D register</span>
<span class="ne">----&gt; </span><span class="mi">2</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]))</span>
<span class="g g-Whitespace">      </span><span class="mi">3</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">))</span>

<span class="ne">RuntimeError</span>: Cannot add qubit with ID &quot;a[1, 2]&quot; as register is not compatible
</pre></div>
</div>
</div>
</div>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># rejected because a[0] is already in the circuit</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output traceback highlight-ipythontb notranslate"><div class="highlight"><pre><span></span><span class="gt">---------------------------------------------------------------------------</span>
<span class="ne">RuntimeError</span><span class="g g-Whitespace">                              </span>Traceback (most recent call last)
<span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">15</span><span class="o">-</span><span class="mi">4739</span><span class="n">be8c694a</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<span class="g g-Whitespace">      </span><span class="mi">1</span> <span class="c1"># rejected because a[0] is already in the circuit</span>
<span class="ne">----&gt; </span><span class="mi">2</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>

<span class="ne">RuntimeError</span>: A unit with ID &quot;a[0]&quot; already exists
</pre></div>
</div>
</div>
</div>
<p>The basic integer identifiers are actually a special case, referring to the default qubit (<code class="docutils literal notranslate"><span class="pre">q[i]</span></code>) and bit (<code class="docutils literal notranslate"><span class="pre">c[i]</span></code>) registers. We can create the <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code> using the nameless <code class="xref py py-class docutils literal notranslate"><span class="pre">Qubit</span></code> and <code class="xref py py-class docutils literal notranslate"><span class="pre">Bit</span></code> constructors.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span><span class="p">,</span> <span class="n">Bit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;q&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>    <span class="c1"># same as circ.CX(0, 1)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Measure</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">Bit</span><span class="p">(</span><span class="s2">&quot;c&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="c1"># same as circ.Measure(2, 0)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Measure q[2] --&gt; c[0]; CX q[0], q[1]; ]
</pre></div>
</div>
</div>
</div>
<p>In some circumstances, it may be useful to rename the resources in the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>. Given a partial map on <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code> s, <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.rename_units()</span></code> will change the association of IDs to resources (as long as the final labelling would still have consistent types for all registers). Any unspecified IDs will be preserved.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span><span class="p">,</span> <span class="n">Bit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qubit</span><span class="p">(</span><span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>

<span class="nb">map</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="p">:</span> <span class="n">Qubit</span><span class="p">(</span><span class="mi">3</span><span class="p">),</span>
    <span class="n">Qubit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">:</span> <span class="n">Qubit</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
    <span class="n">Bit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">:</span> <span class="n">Bit</span><span class="p">(</span><span class="s2">&quot;z&quot;</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]),</span>
<span class="p">}</span>
<span class="n">circ</span><span class="o">.</span><span class="n">rename_units</span><span class="p">(</span><span class="nb">map</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">qubits</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">bits</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[a[0], q[0], q[3]]
[c[1], z[0, 1]]
</pre></div>
</div>
</div>
</div>
</div>
<div class="section" id="composing-circuits">
<h2>Composing Circuits<a class="headerlink" href="#composing-circuits" title="Permalink to this headline"></a></h2>
<p>Because <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s are defined to have open inputs and outputs, it is perfectly natural to compose them by unifying the outputs of one with the inputs of another. Appending one <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> to the end of another matches the inputs and outputs with the same <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span><span class="p">,</span> <span class="n">Bit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rz</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">measures</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">measures</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">measures</span><span class="o">.</span><span class="n">measure_all</span><span class="p">()</span>

<span class="n">circ</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">measures</span><span class="p">)</span>
<span class="n">circ</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[CX q[0], q[1]; Rz(0.3) q[1]; CX q[0], q[1]; Measure q[0] --&gt; c[0]; H q[1]; Measure q[1] --&gt; c[1]; ]
</pre></div>
</div>
</div>
</div>
<p>If one <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> lacks some unit present in the other, then we treat it as if it is an identity on that unit. In the extreme case where the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s are defined with disjoint sets of <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code> s, the <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.append()</span></code> method will compose them in parallel.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_q_register</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

<span class="nb">next</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="n">b</span> <span class="o">=</span> <span class="nb">next</span><span class="o">.</span><span class="n">add_q_register</span><span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="nb">next</span><span class="o">.</span><span class="n">Z</span><span class="p">(</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="nb">next</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

<span class="n">circ</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">next</span><span class="p">)</span>
<span class="n">circ</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(0.2) a[0]; Z b[0]; CX a[0], a[1]; CZ b[1], b[0]; ]
</pre></div>
</div>
</div>
</div>
<p>To change which units get unified, we could use <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.rename_units()</span></code> as seen before, but in the case where we just want to append a subcircuit like a gate, we can do this with <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.add_circuit()</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Qubit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_q_register</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

<span class="nb">next</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="nb">next</span><span class="o">.</span><span class="n">Z</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="nb">next</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="n">circ</span><span class="o">.</span><span class="n">add_circuit</span><span class="p">(</span><span class="nb">next</span><span class="p">,</span> <span class="p">[</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]])</span>

<span class="c1"># This is equivalent to:</span>
<span class="c1"># temp = next.copy()</span>
<span class="c1"># temp.rename_units({Qubit(0) : a[1], Qubit(1) : a[0]})</span>
<span class="c1"># circ.append(temp)</span>

<span class="n">circ</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(0.2) a[0]; CX a[0], a[1]; Z a[1]; CZ a[0], a[1]; ]
</pre></div>
</div>
</div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This requires the subcircuit to be defined only over the default registers so that the list of arguments given to <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.add_circuit()</span></code> can easily be mapped.</p>
</div>
</div>
<div class="section" id="boxes">
<h2>Boxes<a class="headerlink" href="#boxes" title="Permalink to this headline"></a></h2>
<p>Working with individual basic gates is sufficient for implementing arbitrary circuits, but that doesn’t mean it is the most convenient option. It is generally far easier to argue the correctness of a circuit’s design when it is constructed using higher-level constructions. In <code class="docutils literal notranslate"><span class="pre">pytket</span></code>, the concept of a “Box” is to abstract away such complex structures as black-boxes within larger circuits.</p>
<p>The simplest example of this is a <code class="xref py py-class docutils literal notranslate"><span class="pre">CircBox</span></code>, which wraps up another <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> defined elsewhere into a single black-box. The difference between adding a <code class="xref py py-class docutils literal notranslate"><span class="pre">CircBox</span></code> and just appending the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> is that the <code class="xref py py-class docutils literal notranslate"><span class="pre">CircBox</span></code> allows us to wrap up and abstract away the internal structure of the subcircuit we are adding so it appears as if it were a single gate when we view the main <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">CircBox</span>
<span class="n">sub</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">sub</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rz</span><span class="p">(</span><span class="mf">0.2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">sub_box</span> <span class="o">=</span> <span class="n">CircBox</span><span class="p">(</span><span class="n">sub</span><span class="p">)</span>

<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">sub_box</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">sub_box</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">])</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[CircBox q[0], q[1]; X q[1]; CircBox q[1], q[2]; ]
</pre></div>
</div>
</div>
</div>
<p>Similarly, if our subcircuit is a pure quantum circuit (i.e. it corresponds to a unitary operation), we can construct the controlled version that is applied coherently according to some set of control qubits. If all control qubits are in the <span class="math notranslate nohighlight">\(|1\rangle\)</span> state, then the unitary is applied to the target system, otherwise it acts as an identity.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">CircBox</span><span class="p">,</span> <span class="n">QControlBox</span>
<span class="n">sub</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">sub</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rz</span><span class="p">(</span><span class="mf">0.2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">sub_box</span> <span class="o">=</span> <span class="n">CircBox</span><span class="p">(</span><span class="n">sub</span><span class="p">)</span>
<span class="n">cont</span> <span class="o">=</span> <span class="n">QControlBox</span><span class="p">(</span><span class="n">sub_box</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>              <span class="c1"># Define the controlled operation with 2 control qubits</span>

<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">sub_box</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="mf">0.8</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_qcontrolbox</span><span class="p">(</span><span class="n">cont</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>    <span class="c1"># Add to circuit with controls q[0], q[1], and targets q[2], q[3]</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Ry(0.3) q[0]; Ry(0.8) q[1]; CircBox q[2], q[3]; qif (q[0], q[1]) CircBox q[2], q[3]; ]
</pre></div>
</div>
</div>
</div>
<p>As well as creating controlled boxes, we can create a controlled version of an arbitrary <code class="xref py py-class docutils literal notranslate"><span class="pre">Op</span></code> as follows.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Op</span><span class="p">,</span> <span class="n">OpType</span><span class="p">,</span> <span class="n">QControlBox</span>
<span class="n">op</span> <span class="o">=</span> <span class="n">Op</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">S</span><span class="p">)</span>
<span class="n">ccs</span> <span class="o">=</span> <span class="n">QControlBox</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
</div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Whilst adding a control qubit is asymptotically efficient, the gate overhead is significant and can be hard to synthesise optimally, so using these constructions in a NISQ context should be done with caution.</p>
</div>
<p>It is possible to specify small unitaries from <code class="docutils literal notranslate"><span class="pre">numpy</span></code> arrays and embed them directly into circuits as boxes, which can then be synthesised into gate sequences during compilation.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">Unitary1qBox</span><span class="p">,</span> <span class="n">Unitary2qBox</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="n">u1</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">([[</span><span class="o">-</span><span class="mf">0.7487011587786401</span><span class="o">+</span><span class="mf">0.4453416229024393</span><span class="n">j</span><span class="p">,</span> <span class="mf">0.4061474383265779</span><span class="o">+</span><span class="mf">0.2759740424295397</span><span class="n">j</span><span class="p">],</span>
                 <span class="p">[</span><span class="o">-</span><span class="mf">0.12329679104996497</span><span class="o">+</span><span class="mf">0.4753054965713359</span><span class="n">j</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.8565044726815658</span><span class="o">+</span><span class="mf">0.15900526570629525</span><span class="n">j</span><span class="p">]])</span>
<span class="n">u1box</span> <span class="o">=</span> <span class="n">Unitary1qBox</span><span class="p">(</span><span class="n">u1</span><span class="p">)</span>
<span class="n">u2</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">([[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
                 <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">],</span>
                 <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
                 <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="n">j</span><span class="p">,</span> <span class="mi">0</span><span class="p">]])</span>
<span class="n">u2box</span> <span class="o">=</span> <span class="n">Unitary2qBox</span><span class="p">(</span><span class="n">u2</span><span class="p">)</span>

<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_unitary1qbox</span><span class="p">(</span><span class="n">u1box</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_unitary2qbox</span><span class="p">(</span><span class="n">u2box</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_unitary1qbox</span><span class="p">(</span><span class="n">u1box</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_unitary2qbox</span><span class="p">(</span><span class="n">u2box</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[Unitary1qBox q[0]; Unitary2qBox q[1], q[2]; Unitary2qBox q[1], q[0]; Unitary1qBox q[2]; ]
</pre></div>
</div>
</div>
</div>
<p>Another notable example that is common to many algorithms and high-level circuit descriptions is the exponential of a Pauli tensor: <span class="math notranslate nohighlight">\(e^{-i \pi \theta P}\)</span> (<span class="math notranslate nohighlight">\(P \in \{I, X, Y, Z\}^{\otimes n}\)</span>). These occur very naturally in Trotterising evolution operators and as common native device operations.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">PauliExpBox</span>
<span class="kn">from</span> <span class="nn">pytket.pauli</span> <span class="kn">import</span> <span class="n">Pauli</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_pauliexpbox</span><span class="p">(</span><span class="n">PauliExpBox</span><span class="p">([</span><span class="n">Pauli</span><span class="o">.</span><span class="n">X</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">],</span> <span class="mf">0.1</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_pauliexpbox</span><span class="p">(</span><span class="n">PauliExpBox</span><span class="p">([</span><span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">X</span><span class="p">],</span> <span class="o">-</span><span class="mf">0.1</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_pauliexpbox</span><span class="p">(</span><span class="n">PauliExpBox</span><span class="p">([</span><span class="n">Pauli</span><span class="o">.</span><span class="n">X</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">],</span> <span class="mf">0.2</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_pauliexpbox</span><span class="p">(</span><span class="n">PauliExpBox</span><span class="p">([</span><span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">X</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">,</span> <span class="n">Pauli</span><span class="o">.</span><span class="n">Y</span><span class="p">],</span> <span class="o">-</span><span class="mf">0.2</span><span class="p">),</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[PauliExpBox q[0], q[1]; PauliExpBox q[0], q[1]; PauliExpBox q[0], q[1], q[2], q[3]; PauliExpBox q[0], q[1], q[2], q[3]; ]
</pre></div>
</div>
</div>
</div>
</div>
<div class="section" id="analysing-circuits">
<h2>Analysing Circuits<a class="headerlink" href="#analysing-circuits" title="Permalink to this headline"></a></h2>
<p>After creating a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>, we will typically want to inspect what we have constructed to ensure that it agrees with the design we planned. The most basic form of this is to just get the object to return the sequence of operations back to us. Iterating through the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> object will give back the operations as <code class="xref py py-class docutils literal notranslate"><span class="pre">Command</span></code> s (specifying the operations performed and what (qu)bits they are performed on).</p>
<p>Because the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> class identifies circuits up to DAG equivalence, the sequence will be some topological sort of the DAG, but not necessarily identical to the order the operations were added to the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="k">for</span> <span class="n">com</span> <span class="ow">in</span> <span class="n">circ</span><span class="p">:</span> <span class="c1"># equivalently, circ.get_commands()</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">com</span><span class="o">.</span><span class="n">op</span><span class="p">,</span> <span class="n">com</span><span class="o">.</span><span class="n">op</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="n">com</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
    <span class="c1"># NOTE: com is not a reference to something inside circ; this cannot be used to modify the circuit</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>CX OpType.CX [q[0], q[1]]
Rx(0.3) OpType.Rx [q[0]]
CZ OpType.CZ [q[1], q[2]]
X OpType.X [q[1]]
</pre></div>
</div>
</div>
</div>
<p>If you are working in a Jupyter environment, a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> can be rendered using html for inline display.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">pytket.circuit.display</span> <span class="kn">import</span> <span class="n">render_circuit_jupyter</span>

<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">render_circuit_jupyter</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_html">


















<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

<style>
body, .circuit__preview-body {
    font-family: "roboto", system-ui, sans-serif;
    --accent-col: green;
    --accent-col-fill: darkseagreen;
    --accent-col-alt: #aca;
    --accent-col-emph: limegreen;
    --accent-col-overlay: rgba(130,255,140,0.2);
    --accent-col-outline: rgba(30, 250, 30,0.2);
    --main-col: black;
    --mid-col: #bbb;
    --faint-col: #eee;
    --faint-col-overlay: rgba(0, 0, 0, 0.05);
    --main-bg: white;
}

.row{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    padding: 10px;
    border-bottom: 1px solid var(--faint-col);
    position: relative;
}
.row-item{
    flex-grow: 1
}
.row-item-l{
    text-align: left;
}
.row-item-r{
    text-align: right;
}
.row-sub-heading{
    border-color: var(--accent-col-emph);
}

/* FOR DISPLAYING CIRCUITS */
/* Main preview container */
.circuit-preview {
    width: 100%;
    height: 100%;
    text-align: center;
    color: black;
}
.circuit_variables {
    /* Define some variables */
    --box-height: 40px;
    --wire-col: black;
    --c-wire-col: #bbb;
    --box-col: #ccc;
    --box-col-overlay: rgba(0,0,0,0.05);
    --c-box-col: #ddd;
    --index-col: #888;
}
.circuit-preview.condensed{
    display: flex;
    flex-wrap: nowrap;
}

/* Box colours */
.h {
    --box-col: #ffee00;
    --box-col-overlay: rgba(255, 255, 0, 0.2);
    --c-box-col: #ffee88;
    --index-col: #ffcc00;
}
.x {
    --box-col: #ff8888;
    --box-col-overlay: rgba(255, 0, 0, 0.2);
    --c-box-col: #e8a6a6;
    --index-col: red;
}
.y {
    --box-col: #6699ff;
    --box-col-overlay: rgba(0, 0, 255, 0.2);
    --c-box-col: #86c6f6;
    --index-col: blue;
}
.z {
    --box-col: #ccffcc;
    --box-col-overlay: rgba(0, 255, 0, 0.2);
    --c-box-col: #e2ffe2;
    --index-col: green;
}

.circuit-container{
    max-width: 100%;
    display: flex;
    flex-flow: row wrap;
    justify-content: center;
    align-content: flex-start;
    margin: auto;
    width: -moz-fit-content;
    width: fit-content;
    background: rgba(255, 255, 255, 1);
}
.circuit-preview.condensed > .circuit-container{
    flex-wrap: nowrap;
    min-width: fit-content;
}
.circuit-container.nested{
    position: relative;
    flex-wrap: nowrap;
    margin: -2px 0;
}
.nested-circuit-container{
    display: flex;
    overflow: auto;
    max-width: 400px;
    background: var(--box-col-overlay);
    border: 1px solid var(--box-col);
}
.nested-circuit-container::-webkit-scrollbar {
    height: 0;
    width: 0;
}
.circuit-inner-scroll{
    overflow: visible;
    width: -moz-fit-content;
    width: fit-content;
    margin: auto;
    margin-top: 2px;
}
.circuit-end{
    width: 2px;
    height: auto;
    border: 2px solid var(--wire-col);
    margin: calc(var(--box-height)/2) 0 calc(var(--box-height)/2 + 20px);
}
.circuit-layer{
    min-width: 40px;
    width: max-content;
    display: flex;
    flex-flow: column nowrap;
    flex-grow: 1;
    justify-content: space-between;
    align-items: stretch;
    margin-bottom: 20px;
}
.circuit-container:not(.nested) > .circuit-layer:nth-child(2),
.circuit-container:not(.nested) > .circuit-layer:nth-last-child(2),
.circuit-container.nested > .circuit-layer:nth-child(2),
.circuit-container.nested > .circuit-layer:nth-last-child(2),
.gate_container.nested > .circuit-layer:first-child,
.gate_container.nested > .circuit-layer:last-child{
    min-width: 10px;
}
.nested .circuit-layer{
    margin-bottom: 0;
}
.flex_wire{
    flex-grow: 1;
}
/* Display qubit names at start of circuit */
.circuit-layer.qubits{
    flex-grow: 0;
    color: var(--wire-col);
}
.qubit{
    height: calc(var(--box-height) - 20px);
    padding: 10px;
    text-align: center;
    font-family: monospace;
    box-sizing: content-box;
}
.wire{
    height: 0;
    border: 1px solid var(--wire-col);
    background: var(--wire-col);
    margin: calc(var(--box-height)/2) 0;
}
.wire.classical{
    border-color: var(--c-wire-col) !important;
    background: var(--c-wire-col) !important;
}
.wire.transparent-wire{
    border-color: transparent;
    background: transparent;
}

/* Generic base for our gates */
.gate_container{
    position: relative;
    min-width: -moz-fit-content;
    min-width: fit-content;
}
.gate_container.nested{
    display: flex;
    flex-wrap: nowrap;
}
.gate_container.nested:after{
    display: flex;
    flex-wrap: nowrap;
}
.gate_container .classical{
    background: var(--c-box-col);
    border-color: var(--index-col);
}
.gate{
    position: relative;
    height: calc(var(--box-height) - 16px);
    margin: 0 9px;
    padding: 9px 5px;
    border: 1px solid var(--index-col);
    border-bottom: none;
    border-top: none;
    text-align: left;
    background: var(--box-col);
    display: flex;
    box-sizing: content-box;
    z-index: 1;
}
.wire-label{
    color: var(--index-col);
    width: -moz-fit-content;
    width: fit-content;
    height: calc(var(--box-height) - 18px);
    padding-right: 5px;
}
.gate_top > .wire-label,
.gate_bottom > .wire-label {
    padding-top: 0;
}
.nested-label-layer{
    background: var(--box-col);
    padding: 0 5px;
}
.nested-label-layer .wire-label{
    padding: 10px 0;
}

/* Multi-qubit gates */
.gate_bottom{
    height: calc(var(--box-height) - 18px);
    margin-bottom: 10px;
    padding-bottom: 0;
    border-bottom: 1px solid var(--index-col);
}
.gate_top{
    height: calc(var(--box-height) - 18px);
    margin-top: 10px;
    padding-top: 0;
    border-top: 1px solid var(--index-col);
}
.gate_name{
    text-align: center;
    flex-grow: 1;
}
/* Single qubit gate*/
.gate_box{
    height: calc(var(--box-height) - 20px);
    margin: 10px;
    padding: 0 5px;
    border: 1px solid var(--index-col);
    text-align: center;
}

/* Special gates */
.gate_connection {
    position: absolute;
    top: -3px;
    left: -1px;
    border: none;
    margin: calc(var(--box-height)/2) calc(50% - 5px);
    padding: 0;
}
.gate_swap {
    height: 20px;
    width: 20px;
    margin: calc(var(--box-height)/2 - 6px) calc(50% - 9px);
    background: url(
data:image/svg+xml;utf8,%0A%3C%21--%20Generated%20with%20http%3A//jxnblk.com/paths%20--%3E%0A%3Csvg%0A%20%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%0A%20%20viewBox%3D%270%200%2064%2064%27%0A%20%20width%3D%2764%27%20height%3D%2764%27%0A%20%20fill%3D%27currentcolor%27%3E%0A%20%20%3Cpath%20d%3D%27M60%200%20L32%2028%20L4%200%20L0%204%20L28%2032%20L0%2060%20L4%2064%20L32%2036%20L60%2064%20L64%2060%20L36%2032%20L64%204%27%20/%3E%0A%3C/svg%3E
) center;
    background-size: cover;
}
.gate_measure {
    height: 20px;
    width: 25px;
    margin: calc(var(--box-height)/2 - 10px) calc(50% - 11px);
    background: url(
data:image/svg+xml;utf8,%0A%3C%21--%20Generated%20with%20http%3A//jxnblk.com/paths%20--%3E%0A%3Csvg%0A%20%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%0A%20%20viewBox%3D%27-10%20-10%2084%2084%27%0A%20%20width%3D%2764%27%20height%3D%2764%27%0A%20%20fill%3D%27white%27%0A%20%20stroke%3D%22black%22%0A%20%20stroke-width%3D%224px%22%0A%3E%0A%20%20%3Cpath%20d%3D%27M63%2C63%20C63%2C32%2048%2C16%2032%2C16%20C16%2C16%201%2C32%201%2C63%20L63%2C63%27%20/%3E%0A%20%20%3Cpath%20d%3D%22M32%2C63%20L56%2C16%22%20/%3E%0A%3C/svg%3E
) center;
    background-size: cover;
}
.gate_control {
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 50%;
    width: 6px;
    height: 6px;
    margin: calc(var(--box-height)/2 - 3px) calc(50% - 5px);
    padding: 0;
    border: 2px solid var(--wire-col);
    background: var(--box-col);
}
.gate_control.classical{
    background: var(--c-wire-col);
    border-color: var(--c-wire-col);
}
.control_index{
    position: absolute;
    right: calc(50% - 1em);
    top: calc(50% - 1.4em);
    color: var(--c-wire-col);
    font-size: 0.8em;
}
.control_index.measure{
    right: calc(50% - 1.2em);
    top: calc(50% - 1.8em);
    color: var(--index-col);
}
.gate_x {
    top: -10px;
    left: -6px;
    border-radius: 50%;
    border: 1px solid var(--wire-col);
    width: 20px;
    background: url(
data:image/svg+xml;utf8,%0A%3C%21--%20Generated%20with%20http%3A//jxnblk.com/paths%20--%3E%0A%3Csvg%0A%20%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%0A%20%20viewBox%3D%270%200%2064%2064%27%0A%20%20width%3D%2764%27%20height%3D%2764%27%0A%20%20fill%3D%27currentcolor%27%3E%0A%20%20%3Cpath%20d%3D%27M36%2064%20L36%2036%20L64%2036%20L64%2028%20L36%2028%20L36%200%20L28%200%20L28%2028%20L0%2028%20L0%2036%20L28%2036%20L28%2064%27%20/%3E%0A%3C/svg%3E
) center;
    background-color: var(--box-col);
    background-size: cover;
}
.gate_reset{
    margin: 11px 10px;
    padding: 0 0 0 10px;
    border: none !important;
    border-left: 2px solid var(--wire-col) !important;
    background: transparent;
}
.gate_reset_spider{
    width: calc(var(--box-height) - 24px);
    height: calc(var(--box-height) - 24px);
    background: var(--box-col);
    border: 2px solid var(--wire-col);
    border-radius: 50%;
    font-size: 0.75em;
}

/* Add wire sections coming in and out of the gate */
.gate_in:before, .gate_in:after{
    content: '';
    position: absolute;
    display: block;
    top: calc(50% - 1px);
    border: 1px solid var(--wire-col);
    width: 9px;
    height: 0;
    background: var(--wire-col);
    box-sizing: content-box;
}
.classical.gate_in:before,
.classical.gate_in:after{
    border-color: var(--c-wire-col);
}

.gate_in:before{
    left: -12px;
}
.gate_out:after{
    right: -12px;
}
.gate_top.gate_in:before, .gate_top.gate_out:after{
    top:calc(50% - 6.5px)
}
.gate_bottom.gate_in:before, .gate_bottom.gate_out:after{
    top:calc(50% + 4.5px)
}


.link-bottom, .link-top {
    height: var(--box-height);
    width: 0;
    border: 1px solid var(--wire-col);
    background: var(--wire-col);
    position: absolute;
    display: block;
    left: calc(50% - 1px);
    box-sizing: content-box;
}
.link-top{
    top: calc(0px - var(--box-height)/2);
}
.link-bottom{
    top: calc(var(--box-height)/2)
}
.half-link {
    height: calc(var(--box-height) - 9px);
}
.half-link.link-bottom{
    top: calc(var(--box-height)/2 + 11px)
}
.half-link.link-top{
    top: calc(-2px - var(--box-height)/2);
}
.link-bottom.measurement{
    width: 3px;
    left: calc(50% - 0.5px);
    border: none;
    background: var(--c-wire-col);
    height: calc(var(--box-height) + 2px);
    z-index: 1;
}



/* tool tips */
.tool-tip-container{
    margin: calc(0px - var(--box-height)) auto 0;
    padding-top: var(--box-height);
    position: relative;
    bottom: 0;
    left: 0;
    right: 0;
    height: 0;
    z-index: 4;
    width: fit-content;
    overflow: hidden;
}
.tool-tip-container.no-js{
    overflow: visible;
}
.tool-tip-container.no-js:hover{
    z-index: 10;
}
.nested > .tool-tip-container{
    position: absolute;
    bottom: -10px;
}
.tool-tip{
    visibility: hidden;
    opacity: 0;
    -webkit-transition: visibility 0.2s, opacity 0.2s;
    -moz-transition: visibility 0.2s, opacity 0.2s;
    transition: visibility 0.2s, opacity 0.2s;
    max-width: 250px;
}
.tool-tip-container.no-js:hover > .tool-tip{
    visibility: visible;
    opacity: 1;
}
.tool-tip-content{
    background: var(--main-bg);
    margin: 0 auto;
    width: -moz-fit-content;
    width: fit-content;
    max-width: 100%;
}
.no-js > .tool-tip > .tool-tip-content{
    height: auto;
    padding: 20px;
    margin: 0 auto;
}
.tool-tip-container.no-js:hover > .tool-tip > .tool-tip-content,
.no-js > tool-tip > .tool-tip-content:hover{
    box-shadow: 0 -5px 20px 5px var(--faint-col-overlay);
}
.tool-tip:after{
    content: " ";
    position: absolute;
    bottom: 0;
    left: 50%;
    margin-left: -5px;
    border-width: 5px;
    border-style: solid;
    border-color: transparent transparent var(--main-bg) transparent;
}
.tool-tip .complex-number{
    padding: 4px;
}
.tool-tip-content > .gate_container.nested{
    width: 100%;
    min-width: unset;
}
.nested-label-layer.as-height{
    padding: 0;
}
.tool-tip-content > .gate_container.nested > .nested-circuit-container,
.circuit-preview.condensed > .nested-circuit-container{
    background: transparent;
    border: none;
    width: 100%;
    min-width: unset;
    max-width: unset;
}

/* Tool-tip modal */
.circuit-grid{
    display: flex;
    flex-direction: row-reverse;
    align-items: stretch;
    align-content: stretch;
}
.circuit-grid-circuit{
    flex: 1 1 auto;
    margin-top: 30px;
    overflow: auto;
    max-height: inherit;
}




/*  FOR DISPLAYING CHARTS  */
table{
    border-collapse: collapse;
}
.table-container{
    margin: auto;
}
.bar-chart-container{
    min-width: 300px;
    width: 60%;
}
.square-chart-container{
    width: auto;
    min-width: 0;
    overflow: hidden;
}

/* Make sure we can see the rightmost border */
.square-chart-container tbody{
    position: relative;
    left: -1px;
    display: block;
}
thead > tr{
    background: transparent !important;
}
tr:hover, tr {
    background: initial !important;
}

td, th{
    padding: 10px;
    position: relative;
}

/* COMPLEX NUMBERS AND MATRICES */
.complex-number{
    padding: 10px;
}
.mid-number{
    padding: 5px;
    font-size: 0.75em;
}
.large-number{
    padding: 2px;
    font-size: 0.75em;
}
.matrix_container{
    border: 2px solid var(--mid-col);
    border-top: 0;
    border-bottom: 0;
    margin: auto !important;
    border-collapse: collapse;
    text-align: center;
}


/* LIST RESULTS NICELY */
.list{
    flex-wrap: wrap;
    justify-content: space-evenly;
    align-items: stretch;
    padding: 0;
}
.list > *{
    margin: 10px;
}
.list > .row-sub-heading{
    margin: 10px 0;
}
</style>

</head>
<body>
    <div class="row circuit-grid circuit__preview-body">
        <div class="circuit-grid-circuit thin-scrollbar"  style="">















































    <div class="circuit-preview circuit_variables condensed">


            <div class="nested-label-layer as-height">

                    <div class="wire-label"></div>

                    <div class="wire-label"></div>

                    <div class="wire-label"></div>

            </div>
            <div class="nested-circuit-container"><div class="circuit-inner-scroll">

        <div class="circuit-container nested">
            <div class="circuit-layer qubits">

            <div class="qubit">q[0]</div>

            <div class="qubit">q[1]</div>

            <div class="qubit">q[2]</div>


    </div>

                <div class="circuit-layer hover-highlight-circuit">







            <div class="gate_container">
        <div class="wire "></div>

    </div>

            <div class="gate_container">
        <div class="wire "></div>

    </div>

            <div class="gate_container">
        <div class="wire "></div>

    </div>







            </div>

                <div class="circuit-layer hover-highlight-circuit">









            <div class="gate_container">
                <div class="gate_container">
        <div class="wire "></div>

    </div>

                <div class="gate gate_control z"></div>

            </div>















            <div class="gate_container nested">
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
        <div class="gate_container x">


                <div class="gate gate_box gate_in gate_out ">
                    <span class="gate_name">X</span>
                </div>



                <div class="link-top"></div>

        </div>
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
    </div>


















            <div class="gate_container">
        <div class="wire "></div>

    </div>







            </div>

                <div class="circuit-layer hover-highlight-circuit">







            <div class="gate_container nested">
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
        <div class="gate_container x">


                <div class="gate gate_box gate_in gate_out ">
                    <span class="gate_name">Rx(0.3)</span>
                </div>



        </div>
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
    </div>

















            <div class="gate_container">
                <div class="gate_container">
        <div class="wire "></div>

    </div>

                <div class="gate gate_control z"></div>

            </div>















            <div class="gate_container nested">
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
        <div class="gate_container z">


                <div class="gate gate_box gate_in gate_out ">
                    <span class="gate_name">Z</span>
                </div>



                <div class="link-top"></div>

        </div>
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
    </div>


























            </div>

                <div class="circuit-layer hover-highlight-circuit">







            <div class="gate_container">
        <div class="wire "></div>

    </div>













            <div class="gate_container nested">
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
        <div class="gate_container x">


                <div class="gate gate_box gate_in gate_out ">
                    <span class="gate_name">X</span>
                </div>



        </div>
        <div class="flex_wire">
            <div class="gate_container">
        <div class="wire "></div>

    </div>
        </div>
    </div>













            <div class="gate_container">
        <div class="wire "></div>

    </div>







            </div>

                <div class="circuit-layer hover-highlight-circuit">







            <div class="gate_container">
        <div class="wire "></div>

    </div>

            <div class="gate_container">
        <div class="wire "></div>

    </div>

            <div class="gate_container">
        <div class="wire "></div>

    </div>







            </div>

            <div class="circuit-layer qubits">

            <div class="qubit">q[0]</div>

            <div class="qubit">q[1]</div>

            <div class="qubit">q[2]</div>


    </div>
        </div>

            </div></div>

    </div>




        </div>
    </div>
</body>
</html></div></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">pytket</span></code> also features ways to view the underlying DAG graphically for easier visual inspection.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">pytket.utils</span> <span class="kn">import</span> <span class="n">Graph</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Graph</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span><span class="o">.</span><span class="n">get_DAG</span><span class="p">()</span>   <span class="c1"># Displays in interactive python notebooks</span>
            <span class="c1"># In normal python scripts, use Graph.save_DAG or Graph.view_DAG</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<img alt="_images/manual_circuit_27_0.svg" src="_images/manual_circuit_27_0.svg" /></div>
</div>
<p>The visualisation tool can also describe the interaction graph of a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> consisting of only one- and two-qubit gates – that is, the graph of which qubits will share a two-qubit gate at some point during execution.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">pytket.utils</span> <span class="kn">import</span> <span class="n">Graph</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">ZZPhase</span><span class="p">(</span><span class="mf">0.63</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">CY</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">Graph</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span><span class="o">.</span><span class="n">get_qubit_graph</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<img alt="_images/manual_circuit_28_0.svg" src="_images/manual_circuit_28_0.svg" /></div>
</div>
<p>The full instruction sequence may often be too much detail for a lot of needs, especially for large circuits. Common circuit metrics like gate count and depth are used to approximate the difficulty of running it on a device, providing some basic tools to help distinguish different implementations of a given algorithm.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">n_gates</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">depth</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>4
3
</pre></div>
</div>
</div>
</div>
<p>As characteristics of a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> go, these are pretty basic. In terms of approximating the noise level, they fail heavily from weighting all gates evenly when, in fact, some will be much harder to implement than others. For example, in the NISQ era, we find that most technologies provide good single-qubit gate times and fidelities, with two-qubit gates being much slower and noisier <a class="reference internal" href="manual_intro.html#arut2019" id="id1"><span>[Arut2019]</span></a>. On the other hand, looking forward to the fault-tolerant regime we will expect Clifford gates to be very cheap but the magic <span class="math notranslate nohighlight">\(T\)</span> gates to require expensive distillation procedures <a class="reference internal" href="#brav2005" id="id2"><span>[Brav2005]</span></a> <a class="reference internal" href="#brav2012" id="id3"><span>[Brav2012]</span></a>.</p>
<p>We can use the <code class="xref py py-class docutils literal notranslate"><span class="pre">OpType</span></code> enum class to look for the number of gates of a particular type. We also define <span class="math notranslate nohighlight">\(G\)</span>-depth (for a subset of gate types <span class="math notranslate nohighlight">\(G\)</span>) as the minimum number of layers of gates in <span class="math notranslate nohighlight">\(G\)</span> required to run the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>, allowing for topological reorderings. Specific cases of this like <span class="math notranslate nohighlight">\(T\)</span>-depth and <span class="math notranslate nohighlight">\(CX\)</span>-depth are common to the literature on circuit simplification <a class="reference internal" href="#amy2014" id="id4"><span>[Amy2014]</span></a> <a class="reference internal" href="#meij2020" id="id5"><span>[Meij2020]</span></a>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">OpType</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">T</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">T</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">T</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">n_gates_of_type</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">T</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">n_gates_of_type</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">CX</span><span class="p">)</span>
    <span class="o">+</span> <span class="n">circ</span><span class="o">.</span><span class="n">n_gates_of_type</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">CZ</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">depth_by_type</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">T</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">depth_by_type</span><span class="p">({</span><span class="n">OpType</span><span class="o">.</span><span class="n">CX</span><span class="p">,</span> <span class="n">OpType</span><span class="o">.</span><span class="n">CZ</span><span class="p">}))</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>3
4
2
2
</pre></div>
</div>
</div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Each of these metrics will analyse the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> “as is”, so they will consider each Box as a single unit rather than breaking it down into basic gates, nor will they perform any non-trivial gate commutations (those that don’t just follow by deformation of the DAG) or gate decompositions (e.g. recognising that a <span class="math notranslate nohighlight">\(CZ\)</span> gate would contribute 1 to <span class="math notranslate nohighlight">\(CX\)</span>-count in practice).</p>
</div>
</div>
<div class="section" id="importing-exporting-circuits">
<h2>Importing/Exporting Circuits<a class="headerlink" href="#importing-exporting-circuits" title="Permalink to this headline"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">pytket</span></code> <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s can be natively serializaed and deserialized from JSON-compatible dictionaries, using the <code class="xref py py-meth docutils literal notranslate"><span class="pre">to_dict()</span></code> and <code class="xref py py-meth docutils literal notranslate"><span class="pre">from_dict()</span></code> methods. This is the method of serialization which supports the largest class of circuits, and provides the highest fidelity.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">tempfile</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">OpType</span>

<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">YYPhase</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>

<span class="n">circ_dict</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ_dict</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>

<span class="k">with</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">TemporaryFile</span><span class="p">(</span><span class="s1">&#39;w+&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
    <span class="n">json</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">circ_dict</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span>
    <span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="n">new_circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">fp</span><span class="p">))</span>

<span class="nb">print</span><span class="p">(</span><span class="n">new_circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>{&#39;bits&#39;: [], &#39;commands&#39;: [{&#39;args&#39;: [[&#39;q&#39;, [0]]], &#39;op&#39;: {&#39;params&#39;: [&#39;0.1&#39;], &#39;type&#39;: &#39;Rx&#39;}}, {&#39;args&#39;: [[&#39;q&#39;, [0]], [&#39;q&#39;, [1]]], &#39;op&#39;: {&#39;type&#39;: &#39;CX&#39;}}, {&#39;args&#39;: [[&#39;q&#39;, [0]], [&#39;q&#39;, [1]]], &#39;op&#39;: {&#39;params&#39;: [&#39;0.2&#39;], &#39;type&#39;: &#39;YYPhase&#39;}}], &#39;implicit_permutation&#39;: [[[&#39;q&#39;, [0]], [&#39;q&#39;, [0]]], [[&#39;q&#39;, [1]], [&#39;q&#39;, [1]]]], &#39;phase&#39;: &#39;0.0&#39;, &#39;qubits&#39;: [[&#39;q&#39;, [0]], [&#39;q&#39;, [1]]]}


[Rx(0.1) q[0];, CX q[0], q[1];, YYPhase(0.2) q[0], q[1];]
</pre></div>
</div>
</div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">pytket</span></code> also supports interoperability with a number of other quantum software frameworks and programming languages for easy conversion of existing code and to provide users the freedom to choose their preferred input system and use available high-level packages.</p>
<p>OpenQASM is one of the current industry standards for low-level circuit description languages, featuring named quantum and classical registers, parameterised subroutines, and a limited form of conditional execution. Having bidirectional conversion support allows this to double up as a method of serializing circuits for later use.
Though less expressive than native dictionary serialization, it is widely supported and so serves as a platform-independent method of storing circuits.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.qasm</span> <span class="kn">import</span> <span class="n">circuit_from_qasm</span><span class="p">,</span> <span class="n">circuit_to_qasm_str</span>
<span class="kn">import</span> <span class="nn">tempfile</span><span class="o">,</span> <span class="nn">os</span>

<span class="n">fd</span><span class="p">,</span> <span class="n">path</span> <span class="o">=</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="s2">&quot;.qasm&quot;</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="s2">&quot;&quot;&quot;OPENQASM 2.0;</span>
<span class="s2">include &quot;qelib1.inc&quot;;</span>
<span class="s2">qreg q[2];</span>
<span class="s2">creg c[2];</span>
<span class="s2">h q[0];</span>
<span class="s2">cx q[0], q[1];</span>
<span class="s2">cz q[1], q[0];</span>
<span class="s2">measure q -&gt; c;</span>
<span class="s2">&quot;&quot;&quot;</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">circuit_from_qasm</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circuit_to_qasm_str</span><span class="p">(</span><span class="n">circ</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>OPENQASM 2.0;
include &quot;qelib1.inc&quot;;

qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
cz q[1],q[0];
measure q[0] -&gt; c[0];
measure q[1] -&gt; c[1];

</pre></div>
</div>
</div>
</div>
<p>The core <code class="docutils literal notranslate"><span class="pre">pytket</span></code> package additionally features a converter from Quipper, another circuit description language.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.quipper</span> <span class="kn">import</span> <span class="n">circuit_from_quipper</span>
<span class="kn">import</span> <span class="nn">tempfile</span><span class="o">,</span> <span class="nn">os</span>

<span class="n">fd</span><span class="p">,</span> <span class="n">path</span> <span class="o">=</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="s2">&quot;.quip&quot;</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="s2">&quot;&quot;&quot;Inputs: 0:Qbit, 1:Qbit, 2:Qbit</span>
<span class="s2">QGate[&quot;X&quot;](0)</span>
<span class="s2">QGate[&quot;Y&quot;](1)</span>
<span class="s2">QGate[&quot;Z&quot;](2)</span>
<span class="s2">Outputs: 0:Qbit, 1:Qbit, 2:Qbit</span>
<span class="s2">&quot;&quot;&quot;</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">circuit_from_quipper</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[X q[0];, Y q[1];, Z q[2];]
</pre></div>
</div>
</div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>There are a few features of the Quipper language that are not supported by the converter, which are outlined in the <a class="reference external" href="quipper.html">Quipper API reference</a>.</p>
</div>
<p>Converters for other quantum software frameworks can optionally be included by installing the corresponding extension module. These are additional PyPI packages with names <code class="docutils literal notranslate"><span class="pre">pytket-X</span></code>, which extend the <code class="docutils literal notranslate"><span class="pre">pytket</span></code> namespace with additional features to interact with other systems, either using them as a front-end for circuit construction and high-level algorithms or targeting simulators and devices as backends.</p>
<p>For example, installing the <code class="docutils literal notranslate"><span class="pre">pytket-qiskit</span></code> package will add the <code class="docutils literal notranslate"><span class="pre">tk_to_qiskit</span></code> and <code class="docutils literal notranslate"><span class="pre">qiskit_to_tk</span></code> methods which convert between the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> class from <code class="docutils literal notranslate"><span class="pre">pytket</span></code> and <code class="xref py py-class docutils literal notranslate"><span class="pre">qiskit.QuantumCircuit</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">qiskit</span> <span class="kn">import</span> <span class="n">QuantumCircuit</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">pi</span>
<span class="n">qc</span> <span class="o">=</span> <span class="n">QuantumCircuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">qc</span><span class="o">.</span><span class="n">h</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">qc</span><span class="o">.</span><span class="n">cx</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">qc</span><span class="o">.</span><span class="n">rz</span><span class="p">(</span><span class="n">pi</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="kn">from</span> <span class="nn">pytket.extensions.qiskit</span> <span class="kn">import</span> <span class="n">qiskit_to_tk</span><span class="p">,</span> <span class="n">tk_to_qiskit</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">qiskit_to_tk</span><span class="p">(</span><span class="n">qc</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">measure_all</span><span class="p">()</span>

<span class="n">qc2</span> <span class="o">=</span> <span class="n">tk_to_qiskit</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">qc2</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>     ┌───┐     ┌─┐                      
q_0: ┤ H ├──■──┤M├──────────────────────
     └───┘┌─┴─┐└╥┘┌─────────┐     ┌─┐   
q_1: ─────┤ X ├─╫─┤ Rz(π/2) ├──■──┤M├───
          └───┘ ║ └─────────┘┌─┴─┐└╥┘┌─┐
q_2: ───────────╫────────────┤ X ├─╫─┤M├
                ║            └───┘ ║ └╥┘
c: 3/═══════════╩══════════════════╩══╩═
                0                  1  2 
</pre></div>
</div>
</div>
</div>
</div>
<div class="section" id="symbolic-circuits">
<h2>Symbolic Circuits<a class="headerlink" href="#symbolic-circuits" title="Permalink to this headline"></a></h2>
<p>In practice, it is very common for an experiment to use many circuits with similar structure but with varying gate parameters. In variational algorithms like VQE and QAOA, we are trying to explore the energy landscape with respect to the circuit parameters, realised as the angles of rotation gates. The only differences between iterations of the optimisation procedure are the specific angles of rotations in the circuits. Because the procedures of generating and compiling the circuits typically won’t care what the exact angles are, we can define the circuits abstractly, treating each parameter as an algebraic symbol. The circuit generation and compilation can then be pulled outside of the optimisation loop, being performed once and for all rather than once for each set of parameter values.</p>
<p><code class="docutils literal notranslate"><span class="pre">sympy</span></code> is a widely-used python package for symbolic expressions and algebraic manipulation, defining <code class="xref py py-class docutils literal notranslate"><span class="pre">sympy.Symbol</span></code> objects to represent algebraic variables and using them in <code class="xref py py-class docutils literal notranslate"><span class="pre">sympy.Expression</span></code> s to build mathematical statements and arithmetic expressions. Symbolic circuits are managed in <code class="docutils literal notranslate"><span class="pre">pytket</span></code> by defining the circuit parameters as <code class="xref py py-class docutils literal notranslate"><span class="pre">sympy.Symbol</span></code> s, which can be passed in as arguments to the gates and later substituted for concrete values.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">OpType</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="n">Symbol</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">Symbol</span><span class="p">(</span><span class="s2">&quot;alpha&quot;</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">Symbol</span><span class="p">(</span><span class="s2">&quot;beta&quot;</span><span class="p">)</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">YYPhase</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>

<span class="n">s_map</span> <span class="o">=</span> <span class="p">{</span><span class="n">a</span><span class="p">:</span> <span class="mf">0.3</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span><span class="mf">1.25</span><span class="p">}</span>
<span class="n">circ</span><span class="o">.</span><span class="n">symbol_substitution</span><span class="p">(</span><span class="n">s_map</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(alpha) q[0];, Rx(-2*alpha) q[1];, CX q[0], q[1];, YYPhase(beta) q[0], q[1];]
[Rx(0.3) q[0];, Rx(3.4) q[1];, CX q[0], q[1];, YYPhase(1.25) q[0], q[1];]
</pre></div>
</div>
</div>
</div>
<p>It is important to note that the units of the parameter values will still be in half-turns, and so may need conversion to/from radians if there is important semantic meaning to the parameter values. This can either be done at the point of interpreting the values, or by embedding the conversion into the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="n">Symbol</span><span class="p">,</span> <span class="n">pi</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">Symbol</span><span class="p">(</span><span class="s2">&quot;alpha&quot;</span><span class="p">)</span>     <span class="c1"># suppose that alpha is given in radians</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>       <span class="c1"># convert alpha to half-turns when adding gates</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">a</span><span class="o">/</span><span class="n">pi</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="o">-</span><span class="n">a</span><span class="o">/</span><span class="n">pi</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="n">s_map</span> <span class="o">=</span> <span class="p">{</span><span class="n">a</span><span class="p">:</span> <span class="n">pi</span><span class="o">/</span><span class="mi">4</span><span class="p">}</span>
<span class="n">circ</span><span class="o">.</span><span class="n">symbol_substitution</span><span class="p">(</span><span class="n">s_map</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(0.25) q[0];, CX q[0], q[1];, Ry(3.75) q[0];]
</pre></div>
</div>
</div>
</div>
<p>Substitution need not be for concrete values, but is defined more generally to allow symbols to be replaced by arbitrary expressions, including other symbols. This allows for alpha-conversion or to look at special cases with redundant parameters.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="n">symbols</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">symbols</span><span class="p">(</span><span class="s2">&quot;a b c&quot;</span><span class="p">)</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="n">s_map</span> <span class="o">=</span> <span class="p">{</span><span class="n">a</span><span class="p">:</span> <span class="mi">2</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">:</span> <span class="n">a</span><span class="p">}</span>  <span class="c1"># replacement happens simultaneously, and not recursively</span>
<span class="n">circ</span><span class="o">.</span><span class="n">symbol_substitution</span><span class="p">(</span><span class="n">s_map</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(2*a) q[0];, Rx(b) q[1];, CX q[0], q[1];, Ry(a) q[0];, Ry(a) q[1];]
</pre></div>
</div>
</div>
</div>
<p>There are currently no simulators or devices that can run symbolic circuits algebraically, so every symbol must be instantiated before running. At any time, you can query the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> object for the set of free symbols it contains to check what would need to be instantiated before it can be run.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="n">symbols</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">symbols</span><span class="p">(</span><span class="s2">&quot;a, b&quot;</span><span class="p">)</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">symbol_substitution</span><span class="p">({</span><span class="n">a</span><span class="p">:</span><span class="mf">0.2</span><span class="p">})</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">free_symbols</span><span class="p">())</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">is_symbolic</span><span class="p">())</span>   <span class="c1"># returns True when free_symbols() is non-empty</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>{b}
True
</pre></div>
</div>
</div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>There are some minor drawbacks associated with symbolic compilation. When using <a class="reference external" href="passes.html#pytket._tket.passes.EulerAngleReduction">Euler-angle equations</a> or quaternions for merging adjacent rotation gates, the resulting angles are given by some lengthy trigonometric expressions which cannot be evaluated down to just a number when one of the original angles was parameterised; this can lead to unhelpfully long expressions for the angles of some gates in the compiled circuit. It is also not possible to apply the <a class="reference external" href="passes.html#pytket._tket.passes.KAKDecomposition">KAK decomposition</a> to simplify a parameterised circuit, so that pass will only apply to non-parameterised subcircuits, potentially missing some valid opportunities for optimisation.</p>
</div>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>To see how to use symbolic compilation in a variational experiment, have a look at our <a class="reference external" href="https://github.com/CQCL/pytket/blob/main/examples/ucc_vqe.ipynb">VQE (UCCSD) example</a>.</p>
</div>
<div class="section" id="symbolic-unitaries-and-states">
<h3>Symbolic unitaries and states<a class="headerlink" href="#symbolic-unitaries-and-states" title="Permalink to this headline"></a></h3>
<p>In <a class="reference external" href="https://cqcl.github.io/tket/pytket/api/utils.html#module-pytket.utils.symbolic" title="(in pytket v0.18)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">pytket.utils.symbolic</span></code></a> we provide functions <code class="xref py py-func docutils literal notranslate"><span class="pre">circuit_to_symbolic_unitary()</span></code>, which can calculate the unitary representation of a possibly symbolic circuit, and <code class="xref py py-func docutils literal notranslate"><span class="pre">circuit_apply_symbolic_statevector()</span></code>, which can apply a symbolic circuit to an input statevector and return the output state (effectively simulating it).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">pytket.utils.symbolic</span> <span class="kn">import</span> <span class="n">circuit_apply_symbolic_statevector</span><span class="p">,</span> <span class="n">circuit_to_symbolic_unitary</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="n">Symbol</span><span class="p">,</span> <span class="n">pi</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">Symbol</span><span class="p">(</span><span class="s2">&quot;alpha&quot;</span><span class="p">)</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">a</span><span class="o">/</span><span class="n">pi</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">display</span><span class="p">(</span><span class="n">circuit_apply_symbolic_statevector</span><span class="p">(</span><span class="n">circ</span><span class="p">))</span> <span class="c1"># all zero input state is default if None is provided</span>
<span class="n">circuit_to_symbolic_unitary</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_latex math notranslate nohighlight">
\[\begin{split}\displaystyle \left[\begin{matrix}\cos{\left(\frac{\alpha}{2} \right)}\\0\\0\\- i \sin{\left(\frac{\alpha}{2} \right)}\end{matrix}\right]\end{split}\]</div>
<div class="output text_latex math notranslate nohighlight">
\[\begin{split}\displaystyle \left[\begin{matrix}\cos{\left(\frac{\alpha}{2} \right)} &amp; 0 &amp; - i \sin{\left(\frac{\alpha}{2} \right)} &amp; 0\\0 &amp; \cos{\left(\frac{\alpha}{2} \right)} &amp; 0 &amp; - i \sin{\left(\frac{\alpha}{2} \right)}\\0 &amp; - i \sin{\left(\frac{\alpha}{2} \right)} &amp; 0 &amp; \cos{\left(\frac{\alpha}{2} \right)}\\- i \sin{\left(\frac{\alpha}{2} \right)} &amp; 0 &amp; \cos{\left(\frac{\alpha}{2} \right)} &amp; 0\end{matrix}\right]\end{split}\]</div>
</div>
</div>
<p>The unitaries are calculated using the unitary representation of each <a class="reference external" href="https://cqcl.github.io/tket/pytket/api/optype.html">OpType</a> , and according to the default <a class="reference external" href="manual_backend.html#interpreting-results">ILO BasisOrder convention used in backends</a>.
The outputs are sympy <a class="reference external" href="https://docs.sympy.org/latest/modules/matrices/immutablematrices.html">ImmutableMatrix</a> objects, and use the same symbols as in the circuit, so can be further substituted and manipulated.
The conversion functions use the <a class="reference external" href="https://docs.sympy.org/latest/modules/physics/quantum/index.html">sympy Quantum Mechanics module</a>, see also the <code class="xref py py-func docutils literal notranslate"><span class="pre">circuit_to_symbolic_gates()</span></code> and <code class="xref py py-func docutils literal notranslate"><span class="pre">circuit_apply_symbolic_qubit()</span></code> functions to see how to work with those objects directly.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Unitaries corresponding to circuits with <span class="math notranslate nohighlight">\(n\)</span> qubits have dimensions <span class="math notranslate nohighlight">\(2^n \times 2^n\)</span>, so are computationally very expensive to calculate. Symbolic calculation is also computationally costly, meaning calculation of symbolic unitaries is only really feasible for very small circuits (of up to a few qubits in size). These utilities are provided as way to test the design of small subcircuits to check they are performing the intended unitary. Note also that as mentioned above, compilation of a symbolic circuit can generate long symbolic expressions; converting these circuits to a symbolic unitary could then result in a matrix object that is very hard to work with or interpret.</p>
</div>
</div>
</div>
<div class="section" id="advanced-topics">
<h2>Advanced Topics<a class="headerlink" href="#advanced-topics" title="Permalink to this headline"></a></h2>
<div class="section" id="custom-parameterised-gates">
<h3>Custom parameterised Gates<a class="headerlink" href="#custom-parameterised-gates" title="Permalink to this headline"></a></h3>
<p>The <code class="xref py py-class docutils literal notranslate"><span class="pre">CircBox</span></code> construction is good for subroutines where the instruction sequence is fixed. The <code class="xref py py-class docutils literal notranslate"><span class="pre">CustomGateDef</span></code> construction generalises this to construct parameterised subroutines by binding symbols in the definition circuit and instantiating them at each instance. Any symbolic <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> can be provided as the subroutine definition. Remaining symbols that are not bound are treated as free symbols in the global scope.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">CustomGateDef</span>
<span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="n">symbols</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">symbols</span><span class="p">(</span><span class="s2">&quot;a b&quot;</span><span class="p">)</span>
<span class="n">def_circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">def_circ</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">def_circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">def_circ</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">def_circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="o">-</span><span class="n">a</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">def_circ</span><span class="o">.</span><span class="n">Rz</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="n">gate_def</span> <span class="o">=</span> <span class="n">CustomGateDef</span><span class="o">.</span><span class="n">define</span><span class="p">(</span><span class="s2">&quot;MyCRx&quot;</span><span class="p">,</span> <span class="n">def_circ</span><span class="p">,</span> <span class="p">[</span><span class="n">a</span><span class="p">])</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_custom_gate</span><span class="p">(</span><span class="n">gate_def</span><span class="p">,</span> <span class="p">[</span><span class="mf">0.2</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_custom_gate</span><span class="p">(</span><span class="n">gate_def</span><span class="p">,</span> <span class="p">[</span><span class="mf">0.3</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">])</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">free_symbols</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[MyCRx(0.2) q[0], q[1];, MyCRx(0.3) q[0], q[2];]
{b}
</pre></div>
</div>
</div>
</div>
</div>
<div class="section" id="conditional-gates">
<h3>Conditional Gates<a class="headerlink" href="#conditional-gates" title="Permalink to this headline"></a></h3>
<p>Moving beyond toy circuit examples, many applications of quantum computing require looking at circuits as POVMs for extra expressivity, or introducing error-correcting schemes to reduce the effective noise. Each of these requires performing measurements mid-circuit and then performing subsequent gates conditional on the classical value of the measurement result.</p>
<p>Any <code class="docutils literal notranslate"><span class="pre">pytket</span></code> gate can be made conditional at the point of adding it to the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> by providing the <code class="docutils literal notranslate"><span class="pre">condition</span></code> kwarg. The interpretation of <code class="docutils literal notranslate"><span class="pre">circ.G(q,</span> <span class="pre">condition=reg[0])</span></code> is: “if the  bit <code class="docutils literal notranslate"><span class="pre">[reg[0]</span></code> is set, then perform <code class="docutils literal notranslate"><span class="pre">G(q)</span></code>”.
Conditions on more complicated expressions over the values of <a class="reference external" href="circuit.html#pytket.circuit.Bit">Bit</a> and <a class="reference external" href="circuit.html#pytket.circuit.BitRegister">BitRegister</a> are also possible, expressed as conditions on the results of expressions involving bitwise AND (&amp;), OR (|) and XOR (^) operations.
For example a gate can be made conditional on the result of a bitwise XOR of registers <code class="docutils literal notranslate"><span class="pre">a</span></code>, <code class="docutils literal notranslate"><span class="pre">b</span></code>, and <code class="docutils literal notranslate"><span class="pre">c</span></code> being larger than 4 by writing <code class="docutils literal notranslate"><span class="pre">circ.G(q,</span> <span class="pre">condition=reg_gt(a</span> <span class="pre">^</span> <span class="pre">b</span> <span class="pre">^</span> <span class="pre">c,</span> <span class="pre">4))</span></code>.
When such a condition is added, the result of the expression is written to a scratch bit or register, and the gate is made conditional on the value of the scratch variable.
For comparison of registers, a special <code class="docutils literal notranslate"><span class="pre">RangePredicate</span></code> type is used to encode the result of the comparison onto a scratch bit.
See the <a class="reference external" href="classical.html">API reference</a> for more on the possible expressions and predicates.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="p">(</span>
    <span class="n">Circuit</span><span class="p">,</span>
    <span class="n">BitRegister</span><span class="p">,</span>
    <span class="n">if_bit</span><span class="p">,</span>
    <span class="n">if_not_bit</span><span class="p">,</span>
    <span class="n">reg_eq</span><span class="p">,</span>
    <span class="n">reg_geq</span><span class="p">,</span>
    <span class="n">reg_gt</span><span class="p">,</span>
    <span class="n">reg_leq</span><span class="p">,</span>
    <span class="n">reg_lt</span><span class="p">,</span>
    <span class="n">reg_neq</span><span class="p">,</span>
<span class="p">)</span>
<span class="c1"># create a circuit and add quantum and classical registers</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">()</span>
<span class="n">qreg</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_q_register</span><span class="p">(</span><span class="s2">&quot;q&quot;</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="n">reg_a</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_c_register</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">reg_b</span> <span class="o">=</span> <span class="n">BitRegister</span><span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_c_register</span><span class="p">(</span><span class="n">reg_b</span><span class="p">)</span>
<span class="n">reg_c</span> <span class="o">=</span> <span class="n">circ</span><span class="o">.</span><span class="n">add_c_register</span><span class="p">(</span><span class="s2">&quot;c&quot;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>

<span class="c1"># if (reg_a[0] == 1)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_a</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">circ</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">if_bit</span><span class="p">(</span><span class="n">reg_a</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>

<span class="c1"># if (reg_a[2] == 0)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">T</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">if_not_bit</span><span class="p">(</span><span class="n">reg_a</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span>

<span class="c1"># compound logical expressions</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Z</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="p">(</span><span class="n">reg_a</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="n">reg_a</span><span class="p">[</span><span class="mi">3</span><span class="p">]))</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Z</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">if_not_bit</span><span class="p">(</span><span class="n">reg_a</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="n">reg_a</span><span class="p">[</span><span class="mi">3</span><span class="p">]))</span>
<span class="n">big_exp</span> <span class="o">=</span> <span class="n">reg_a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">|</span> <span class="n">reg_a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">^</span> <span class="n">reg_a</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&amp;</span> <span class="n">reg_a</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
<span class="c1"># syntactic sugar for big_exp = BitOr(reg_a[0], BitXor(reg_a[1], BitAnd(reg_a[2], reg_a[3])))</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">qreg</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">big_exp</span><span class="p">)</span>

<span class="c1"># Register comparisons</span>

<span class="c1"># if (reg_a == 3)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_eq</span><span class="p">(</span><span class="n">reg_a</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># if (reg_c != 6)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Y</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_neq</span><span class="p">(</span><span class="n">reg_c</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
<span class="c1"># if (reg_b &lt; 6)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_lt</span><span class="p">(</span><span class="n">reg_b</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
<span class="c1"># if (reg_b &gt; 3)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Z</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_gt</span><span class="p">(</span><span class="n">reg_b</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># if (reg_c &lt;= 6)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">S</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_leq</span><span class="p">(</span><span class="n">reg_c</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
<span class="c1"># if (reg_a &gt;= 3)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">T</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_geq</span><span class="p">(</span><span class="n">reg_a</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
<span class="c1"># compound register expressions</span>
<span class="n">big_reg_exp</span> <span class="o">=</span> <span class="n">reg_a</span> <span class="o">&amp;</span> <span class="n">reg_b</span> <span class="o">|</span> <span class="n">reg_c</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="n">qreg</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">qreg</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">condition</span><span class="o">=</span><span class="n">reg_eq</span><span class="p">(</span><span class="n">big_reg_exp</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output text_plain highlight-none notranslate"><div class="highlight"><pre><span></span>[IF ([a[0]] == 1) THEN H q[0]; IF ([a[2]] == 0) THEN T q[1]; ClassicalExpBox a[2], a[3], tk_SCRATCH_BIT[0]; ClassicalExpBox a[2], a[3], tk_SCRATCH_BIT[1]; ClassicalExpBox a[0], a[1], a[2], a[3], tk_SCRATCH_BIT[2]; RangePredicate([3,3]) a[0], a[1], a[2], a[3], tk_SCRATCH_BIT[3]; RangePredicate([5,5]) c[0], c[1], c[2], tk_SCRATCH_BIT[4]; RangePredicate([0,5]) b[0], b[1], b[2], tk_SCRATCH_BIT[5]; RangePredicate([4,4294967295]) b[0], b[1], b[2], tk_SCRATCH_BIT[6]; RangePredicate([0,6]) c[0], c[1], c[2], tk_SCRATCH_BIT[7]; RangePredicate([3,4294967295]) a[0], a[1], a[2], a[3], tk_SCRATCH_BIT[8]; ClassicalExpBox a[0], a[1], a[2], a[3], b[0], b[1], b[2], c[0], c[1], c[2], tk_SCRATCH_BITREG_0[0], tk_SCRATCH_BITREG_0[1], tk_SCRATCH_BITREG_0[2]; IF ([a[0]] == 1) THEN X q[0]; IF ([tk_SCRATCH_BIT[1]] == 0) THEN Z q[1]; IF ([tk_SCRATCH_BIT[5]] == 1) THEN X q[3]; IF ([tk_SCRATCH_BIT[4]] == 0) THEN Y q[4]; IF ([tk_SCRATCH_BIT[6]] == 1) THEN Z q[5]; IF ([tk_SCRATCH_BIT[7]] == 1) THEN S q[6]; IF ([tk_SCRATCH_BIT[8]] == 1) THEN T q[7]; RangePredicate([3,3]) tk_SCRATCH_BITREG_0[0], tk_SCRATCH_BITREG_0[1], tk_SCRATCH_BITREG_0[2], tk_SCRATCH_BIT[9]; IF ([tk_SCRATCH_BIT[0]] == 1) THEN Z q[0]; IF ([tk_SCRATCH_BIT[2]] == 1) THEN CX q[1], q[2]; IF ([tk_SCRATCH_BIT[9]] == 1) THEN CX q[3], q[4]; IF ([tk_SCRATCH_BIT[3]] == 1) THEN H q[2]; ]
</pre></div>
</div>
</div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Unlike most uses of readouts in <code class="docutils literal notranslate"><span class="pre">pytket</span></code>, register comparisons expect a little-endian value, e.g. in the above example <code class="docutils literal notranslate"><span class="pre">condition=reg_eq(reg_a,</span> <span class="pre">3)</span></code> (representing the little-endian binary string <code class="docutils literal notranslate"><span class="pre">110000...</span></code>) is triggered when <code class="docutils literal notranslate"><span class="pre">reg_a[0]</span></code> and <code class="docutils literal notranslate"><span class="pre">reg_a[1]</span></code> are in state <code class="docutils literal notranslate"><span class="pre">1</span></code> and the remainder of the register is in state <code class="docutils literal notranslate"><span class="pre">0</span></code>.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This feature is only usable on a limited selection of devices and simulators which support conditional gates.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">Aerbackend</span></code> (from <code class="docutils literal notranslate"><span class="pre">pytket-qiskit</span></code>) can support the OpenQasm model, where gates can only be conditional on an entire classical register being an exact integer value. Bitwise logical operations are not supported. Therefore only conditions of the form
<code class="docutils literal notranslate"><span class="pre">condition=reg_eq(reg,</span> <span class="pre">val)</span></code> are valid.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">HoneywellBackend</span></code> (from <code class="docutils literal notranslate"><span class="pre">pytket-honeywell</span></code>)
can support the full range of expressions and comparisons shown above, as long as the <a class="reference external" href="passes.html#pytket.passes.DecomposeClassicalExp">DecomposeClassicalExp</a> pass  has been run on the circuit first.
This is part of the default compilation pass for that backend, so if you use that you do not need to run it separately.</p>
</div>
</div>
<div class="section" id="circuit-level-operations">
<h3>Circuit-Level Operations<a class="headerlink" href="#circuit-level-operations" title="Permalink to this headline"></a></h3>
<p>Systematic modifications to a <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> object can go beyond simply adding gates one at a time. For example, given a unitary <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code>, we may wish to generate its inverse for the purposes of uncomputation of ancillae or creating conjugation circuits to diagonalise an operator as in the sample below.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="c1"># we want a circuit for E = exp(-i pi (0.3 XX + 0.1 YY))</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>

<span class="c1"># find C such that C; Rx(a, 0); C^dagger performs exp(-i a pi XX/2)</span>
<span class="c1"># and C; Rz(b, 1); C^dagger performs exp(-i b pi YY/2)</span>
<span class="n">conj</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="n">conj</span><span class="o">.</span><span class="n">V</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">V</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">conj_dag</span> <span class="o">=</span> <span class="n">conj</span><span class="o">.</span><span class="n">dagger</span><span class="p">()</span>

<span class="n">circ</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conj</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.6</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Rz</span><span class="p">(</span><span class="mf">0.2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conj_dag</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
</div>
</div>
<p>Generating the transpose of a unitary works similarly using <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.transpose()</span></code>.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Since it is not possible to construct the inverse of an arbitrary POVM, the <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.dagger()</span></code> and <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.transpose()</span></code> methods will fail if there are any measurements, resets, or other operations that they cannot directly invert.</p>
</div>
</div>
<div class="section" id="implicit-qubit-permutations">
<h3>Implicit Qubit Permutations<a class="headerlink" href="#implicit-qubit-permutations" title="Permalink to this headline"></a></h3>
<p>The <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> class is built as a DAG to help follow the paths of resources and represent the circuit canonically up to trivial commutations. Each of the edges represents a resource passing from one instruction to the next, so we could represent SWAPs (and general permutations) by connecting the predecessors of the SWAP instruction to the opposite successors. This eliminates the SWAP instruction from the graph (meaning we would no longer perform the operation at runtime) and could enable the compiler to spot additional opportunities for simplification. One example of this in practice is the ability to convert a pair of CXs in opposite directions to just a single CX (along with an implicit SWAP that isn’t actually performed).</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket</span> <span class="kn">import</span> <span class="n">Circuit</span>
<span class="kn">from</span> <span class="nn">pytket.utils</span> <span class="kn">import</span> <span class="n">Graph</span>
<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CZ</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
<span class="n">Graph</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span><span class="o">.</span><span class="n">get_DAG</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[CX q[0], q[1];, CX q[1], q[0];, Rx(0.2) q[1];, CZ q[0], q[1];]
</pre></div>
</div>
<img alt="_images/manual_circuit_43_1.svg" src="_images/manual_circuit_43_1.svg" /></div>
</div>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.passes</span> <span class="kn">import</span> <span class="n">CliffordSimp</span>
<span class="n">CliffordSimp</span><span class="p">()</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">implicit_qubit_permutation</span><span class="p">())</span>
<span class="n">Graph</span><span class="p">(</span><span class="n">circ</span><span class="p">)</span><span class="o">.</span><span class="n">get_DAG</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[tk1(0.5, 3.8, 1) q[0];, tk1(0, 0, 0.5) q[1];, CX q[1], q[0];, tk1(0, 0, 0.5) q[0];]
{q[0]: q[1], q[1]: q[0], q[2]: q[2], q[3]: q[3]}
</pre></div>
</div>
<img alt="_images/manual_circuit_44_1.svg" src="_images/manual_circuit_44_1.svg" /></div>
</div>
<p>This procedure essentially exploits the naturality of the symmetry operator in the resource theory to push it to the end of the circuit: the <code class="docutils literal notranslate"><span class="pre">Rx</span></code> gate has moved from qubit <code class="docutils literal notranslate"><span class="pre">q[1]</span></code> to <code class="docutils literal notranslate"><span class="pre">q[0]</span></code> and can be commuted through to the start. This is automatically considered when composing two <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s together.</p>
<p>The permutation has been reduced to something implicit in the graph, and we now find that tracing a path from an input can reach an output with a different <code class="xref py py-class docutils literal notranslate"><span class="pre">UnitID</span></code>. Since this permutation is missing in the command sequence, simulating the circuit would only give the correct state up to a permutation of the qubits. This does not matter when running on real devices where the final quantum system is discarded after use, but is detectable when using a statevector simulator. This is handled automatically by <code class="docutils literal notranslate"><span class="pre">pytket</span></code> backends, but care should be taken when reading from the <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> directly - two quantum <code class="xref py py-class docutils literal notranslate"><span class="pre">Circuit</span></code> s can have the same sequence of instructions but different unitaries because of implicit permutations. This permutation information is typically dropped when exporting to another software framework. The <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.implicit_qubit_permutation()</span></code> method can be used to inspect such a permutation.</p>
</div>
<div class="section" id="modifying-operations-within-circuits">
<h3>Modifying Operations Within Circuits<a class="headerlink" href="#modifying-operations-within-circuits" title="Permalink to this headline"></a></h3>
<p>Symbolic parameters allow one to construct a circuit with some not-yet-assigned parameters, and later (perhaps after some optimization), to instantiate them with different values. Occasionally, however, one may desire more flexibility in substituting operations within a circuit. For example, one may wish to apply controls from a certain qubit to certain operations, or to insert or remove certain operations.</p>
<p>This can be achieved with <code class="docutils literal notranslate"><span class="pre">pytket</span></code>, provided the mutable operations are tagged during circuit construction with identifying names (which can be arbitrary strings). If two operations are given the same name then they belong to the same “operation group”; they can (and must) then be substituted simultaneously.</p>
<p>Both primitive gates and boxes can be tagged and substituted in this way. The only constraint is that the signature (number and order of quantum and classical wires) of the substituted operation must match that of the original operation in the circuit. (It follows that all operations in the same group must have the same signature. An attempt to add an operation with an existing name with a mismatching signature will fail.)</p>
<p>To add gates or boxes to a circuit with specified op group names, simply pass the name as a keyword argument <code class="docutils literal notranslate"><span class="pre">opgroup</span></code> to the method that adds the gate or box. To substitute all operations in a group, use the <code class="xref py py-meth docutils literal notranslate"><span class="pre">Circuit.substitute_named()</span></code> method. This can be used to substitute a circuit, an operation or a box into the existing circuit.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Circuit</span><span class="p">,</span> <span class="n">CircBox</span>

<span class="n">circ</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Rz</span><span class="p">(</span><span class="mf">0.25</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;rotations&quot;</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="mf">0.75</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;rotations&quot;</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;special one&quot;</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">cbox</span> <span class="o">=</span> <span class="n">CircBox</span><span class="p">(</span><span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">S</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">CY</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
<span class="n">circ</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">cbox</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;Fred&quot;</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;Fred&quot;</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[[rotations] Rz(0.25) q[0];, [special one] H q[2];, CX q[0], q[1];, [rotations] Ry(0.75) q[1];, CX q[2], q[1];, [Fred] CircBox q[0], q[1];, [Fred] CX q[1], q[2];]
</pre></div>
</div>
</div>
</div>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">Op</span>

<span class="c1"># Substitute a new 1-qubit circuit for all ops in the &quot;rotations&quot; group:</span>
<span class="n">newcirc</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">Rx</span><span class="p">(</span><span class="mf">0.125</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Ry</span><span class="p">(</span><span class="mf">0.875</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">substitute_named</span><span class="p">(</span><span class="n">newcirc</span><span class="p">,</span> <span class="s2">&quot;rotations&quot;</span><span class="p">)</span>
<span class="c1"># Replace the &quot;special one&quot; with a different op:</span>
<span class="n">newop</span> <span class="o">=</span> <span class="n">Op</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">T</span><span class="p">)</span>
<span class="n">circ</span><span class="o">.</span><span class="n">substitute_named</span><span class="p">(</span><span class="n">newop</span><span class="p">,</span> <span class="s2">&quot;special one&quot;</span><span class="p">)</span>
<span class="c1"># Substitute a box for the &quot;Fred&quot; group:</span>
<span class="n">newcbox</span> <span class="o">=</span> <span class="n">CircBox</span><span class="p">(</span><span class="n">Circuit</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">CX</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="n">circ</span><span class="o">.</span><span class="n">substitute_named</span><span class="p">(</span><span class="n">newcbox</span><span class="p">,</span> <span class="s2">&quot;Fred&quot;</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">circ</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[Rx(0.125) q[0];, [special one] T q[2];, Ry(0.875) q[0];, CX q[0], q[1];, Rx(0.125) q[1];, Ry(0.875) q[1];, CX q[2], q[1];, [Fred] CircBox q[0], q[1];, [Fred] CircBox q[1], q[2];]
</pre></div>
</div>
</div>
</div>
<p>Note that when an operation or box is substituted in, the op group name is retained (and further substitutions can be made). When a circuit is substituted in, the op group name disappears.</p>
<p>To remove an operation, one can replace it with an empty circuit.</p>
<p>To add a control to an operation, one can add the original operation as a <code class="xref py py-class docutils literal notranslate"><span class="pre">CircBox</span></code> with one unused qubit, and subtitute it with a <code class="xref py py-class docutils literal notranslate"><span class="pre">QControlBox</span></code>.</p>
<div class="jupyter_cell jupyter_container docutils container">
<div class="cell_input code_cell docutils container">
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">pytket.circuit</span> <span class="kn">import</span> <span class="n">QControlBox</span>

<span class="k">def</span> <span class="nf">with_empty_qubit</span><span class="p">(</span><span class="n">op</span><span class="p">:</span> <span class="n">Op</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">CircBox</span><span class="p">:</span>
    <span class="n">n_qb</span> <span class="o">=</span> <span class="n">op</span><span class="o">.</span><span class="n">n_qubits</span>
    <span class="k">return</span> <span class="n">CircBox</span><span class="p">(</span><span class="n">Circuit</span><span class="p">(</span><span class="n">n_qb</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n_qb</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))))</span>
<span class="k">def</span> <span class="nf">with_control_qubit</span><span class="p">(</span><span class="n">op</span><span class="p">:</span> <span class="n">Op</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">QControlBox</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">QControlBox</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">Circuit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">h_op</span> <span class="o">=</span> <span class="n">Op</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">H</span><span class="p">)</span>
<span class="n">cx_op</span> <span class="o">=</span> <span class="n">Op</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">OpType</span><span class="o">.</span><span class="n">CX</span><span class="p">)</span>
<span class="n">h_0_cbox</span> <span class="o">=</span> <span class="n">with_empty_qubit</span><span class="p">(</span><span class="n">h_op</span><span class="p">)</span>
<span class="n">h_q_qbox</span> <span class="o">=</span> <span class="n">with_control_qubit</span><span class="p">(</span><span class="n">h_op</span><span class="p">)</span>
<span class="n">cx_0_cbox</span> <span class="o">=</span> <span class="n">with_empty_qubit</span><span class="p">(</span><span class="n">cx_op</span><span class="p">)</span>
<span class="n">cx_q_qbox</span> <span class="o">=</span> <span class="n">with_control_qubit</span><span class="p">(</span><span class="n">cx_op</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Y</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">h_0_cbox</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;hgroup&quot;</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">cx_0_cbox</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;cxgroup&quot;</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">Y</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">h_0_cbox</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;hgroup&quot;</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">add_circbox</span><span class="p">(</span><span class="n">cx_0_cbox</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">opgroup</span><span class="o">=</span><span class="s2">&quot;cxgroup&quot;</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">X</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">Y</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">substitute_named</span><span class="p">(</span><span class="n">h_q_qbox</span><span class="p">,</span> <span class="s2">&quot;hgroup&quot;</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">substitute_named</span><span class="p">(</span><span class="n">cx_q_qbox</span><span class="p">,</span> <span class="s2">&quot;cxgroup&quot;</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">get_commands</span><span class="p">())</span>
</pre></div>
</div>
</div>
<div class="cell_output docutils container">
<div class="output stream highlight-none notranslate"><div class="highlight"><pre><span></span>[X q[0];, Y q[1];, [hgroup] qif (q[2]) H q[0];, [cxgroup] qif (q[2]) CX q[0], q[1];, Y q[0];, X q[1];, [hgroup] qif (q[2]) H q[1];, [cxgroup] qif (q[2]) CX q[1], q[0];, X q[0];, Y q[1];]
</pre></div>
</div>
</div>
</div>
<dl class="citation">
<dt class="label" id="brav2005"><span class="brackets"><a class="fn-backref" href="#id2">Brav2005</a></span></dt>
<dd><p>Bravyi, S. and Kitaev, A., 2005. Universal quantum computation with ideal Clifford gates and noisy ancillas. Physical Review A, 71(2), p.022316.</p>
</dd>
<dt class="label" id="brav2012"><span class="brackets"><a class="fn-backref" href="#id3">Brav2012</a></span></dt>
<dd><p>Bravyi, S. and Haah, J., 2012. Magic-state distillation with low overhead. Physical Review A, 86(5), p.052329.</p>
</dd>
<dt class="label" id="amy2014"><span class="brackets"><a class="fn-backref" href="#id4">Amy2014</a></span></dt>
<dd><p>Amy, M., Maslov, D. and Mosca, M., 2014. Polynomial-time T-depth optimization of Clifford+ T circuits via matroid partitioning. IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems, 33(10), pp.1476-1489.</p>
</dd>
<dt class="label" id="meij2020"><span class="brackets"><a class="fn-backref" href="#id5">Meij2020</a></span></dt>
<dd><p>de Griend, A.M.V. and Duncan, R., 2020. Architecture-aware synthesis of phase polynomials for NISQ devices. arXiv preprint arXiv:2004.06052.</p>
</dd>
</dl>
</div>
</div>
</div>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="manual_intro.html" class="btn btn-neutral float-left" title="What is tket?" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
        <a href="manual_backend.html" class="btn btn-neutral float-right" title="Running on Backends" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 2020-2021 Cambridge Quantum Computing Ltd.</p>
  </div>

  Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
    provided by <a href="https://readthedocs.org">Read the Docs</a>.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>